#pragma once

#include <string>
#include <thread>
#include <memory>
#include <optional>
#include <rockchip/mpp_packet.h>
#include <rockchip/rk_mpi.h>
extern "C" {
#include <libavformat/avformat.h>
}

struct FrameStruct
{
    MppBuffer mpp_buffer;
    int fd;
    MppFrameColorSpace mpp_colour_space;
    MppFrameColorRange mpp_colour_range;
    MppFrameColorPrimaries mpp_colour_primaries;
    unsigned int width;
    unsigned int height;
    unsigned int offset_x;
    unsigned int offset_y;
    unsigned int hor_stride;
    unsigned int ver_stride;
};


class Decoder
{
public:
    Decoder();
    ~Decoder();

    void set_mp4_path(const std::string& path);

    bool start();
    void lock();
    bool send_frame();
    bool receive_frame(FrameStruct& frame);

    void frame_created(unsigned int w, unsigned int h, unsigned int hor_stride,
                       unsigned int ver_stride, void* buffer, unsigned int size);
    void frame_invalidate(void* buffer, unsigned int w, unsigned h, unsigned int fd,
                          unsigned int offset_x, unsigned int hor_stride,
                          unsigned int ver_stride, unsigned int size);
//    void frame_invalidate(const QByteArray& buf, unsigned int w, unsigned h, unsigned int size);


private:
    bool init_mpp();
    bool CopyBuffer(const uint8_t* ptr, const size_t size, MppPacket& packet);
    bool SendFrame(MppApi* api, MppCtx context, const uint8_t* ptr, const size_t size, MppPacket& packet);

private:
    std::string m_mp4_path;
    std::unique_ptr<std::thread> m_input_thread;
    std::unique_ptr<std::thread> m_output_thread;

    MppCtx m_ctx;
    MppPacket m_packet;
    MppApi* m_mpi;
    MppBufferGroup m_frm_grp = nullptr;

    AVFormatContext* m_format_context = nullptr;
    std::optional<unsigned int> m_videostream;
    AVPacket* m_av_packet = nullptr;
    size_t m_packet_buffer_size = 64;
    std::unique_ptr<char[]> m_packet_buffer;
};
